package com.zmj.sy.mom.srv.aps.service;

import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.zmj.sy.mom.srv.aps.bean.entity.order.Order;
import com.zmj.sy.mom.srv.aps.bean.entity.resource.DictData;
import com.zmj.sy.mom.srv.aps.bean.entity.resource.DictType;
import com.zmj.sy.mom.srv.aps.bean.vo.base.BaseListResVo;
import com.zmj.sy.mom.srv.aps.bean.vo.consistency.ConsistencyCheckDataResVo;
import com.zmj.sy.mom.srv.aps.bean.vo.consistency.ConsistencyCheckReqVo;
import com.zmj.sy.mom.srv.aps.bean.vo.consistency.ConsistencyCheckResVo;
import com.zmj.sy.mom.srv.aps.config.StrategyConfig;
import com.zmj.sy.mom.srv.aps.mapper.DictDataMapper;
import com.zmj.sy.mom.srv.aps.mapper.DictTypeMapper;
import com.zmj.sy.mom.srv.aps.mapper.OrderMapper;
import com.zmj.sy.mom.srv.aps.utils.SyExceptionUtils;
import com.zmj.sy.mom.srv.aps.utils.diff.DiffRule;
import lombok.RequiredArgsConstructor;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.util.StringUtils;

import java.util.*;
import java.util.stream.Collectors;
import java.util.stream.Stream;

@RequiredArgsConstructor
@Service
public class ConsistencyService {

    private final StrategyConfig strategyConfig;

    private final DictTypeMapper dictTypeMapper;

    private final DictDataMapper dictDataMapper;
    private final OrderMapper orderMapper;


    @Transactional(readOnly = true)
    public BaseListResVo<ConsistencyCheckResVo> check(ConsistencyCheckReqVo reqVo) {

        Map<String, String> dictMap = getReplaceMap();

        DiffRule sourceDiffRule = strategyConfig.getDiffRule(reqVo.getSource());
        List<ConsistencyCheckDataResVo> sourceData = sourceDiffRule.getData(reqVo);

        DiffRule targetDiffRule = strategyConfig.getDiffRule(reqVo.getTarget());
        List<ConsistencyCheckDataResVo> targetData = targetDiffRule.getData(reqVo);

        List<String> allPlmId = Stream.concat(sourceData.stream().map(ConsistencyCheckDataResVo::getWorkOrderCode), targetData.stream().map(ConsistencyCheckDataResVo::getWorkOrderCode)).distinct().collect(Collectors.toList());

        Map<String, ConsistencyCheckDataResVo> sourceMap = sourceData.stream().collect(Collectors.toMap(ConsistencyCheckDataResVo::getWorkOrderCode, e -> e));
        Map<String, ConsistencyCheckDataResVo> targetMap = targetData.stream().collect(Collectors.toMap(ConsistencyCheckDataResVo::getWorkOrderCode, e -> e));


        List<ConsistencyCheckResVo> result = new ArrayList<>();
        for (String plmId : allPlmId) {
            ConsistencyCheckDataResVo source = sourceMap.get(plmId);
            ConsistencyCheckDataResVo target = targetMap.get(plmId);

            ConsistencyCheckResVo current = new ConsistencyCheckResVo();
            wrap(current, 1, source);
            wrap(current, 2, target);

            if (source == null && target == null) {
                throw SyExceptionUtils.e("数据异常，请联系开发");
            }

            if (source == null) {
                addDiff(1, reqVo.getSource() + "找不到该零件", current, result);
                continue;
            }

            if (target == null) {
                addDiff(1, reqVo.getTarget() + "找不到该零件", current, result);
                continue;
            }

            if (!source.getTotalCount().equals(target.getTotalCount())) {
                addDiff(2, "数量不一致", current, result);
                continue;
            }

            String m1 = source.getMaterial() == null? "" : source.getMaterial();
            String m2 = target.getMaterial() == null? "" : target.getMaterial();
            m1 =  dictMap.getOrDefault(m1, m1);
            m2 =  dictMap.getOrDefault(m2, m2);
            if (source.getMaterial() == null || target.getMaterial() == null || !m1.equals(m2)) {
                addDiff(3, "材质不一致", current, result);
                continue;
            }

            if (source.getThickness() == null || target.getThickness() == null || !source.getThickness().equals(target.getThickness())) {
                addDiff(4, "厚度不一致", current, result);
                continue;
            }

            current.setDiffType(0);

            if (StringUtils.hasText(reqVo.getSourcePlmId())) {
                if (!current.getSourcePlmId().contains(reqVo.getSourcePlmId()) || !current.getTargetPlmId().contains(reqVo.getSourcePlmId())) {
                    continue;
                }
            }

            if (StringUtils.hasText(reqVo.getDiffMsg())) {
                if (StringUtils.hasText(current.getDiffMsg()) && !current.getDiffMsg().contains(reqVo.getDiffMsg())) {
                    continue;
                }
            }

            if (StringUtils.hasText(reqVo.getSourceMaterial())) {
                if (!current.getSourceMaterial().contains(reqVo.getSourceMaterial()) || !current.getTargetMaterial().contains(reqVo.getSourceMaterial())) {
                    continue;
                }
            }

            if (reqVo.getSourceTotalCount() != null) {
                if (!Objects.equals(current.getSourceTotalCount(), reqVo.getSourceTotalCount()) || !Objects.equals(current.getTargetTotalCount(), reqVo.getSourceTotalCount())) {
                    continue;
                }
            }

            result.add(current);
        }

        String template = "%sδ%d";
        for (ConsistencyCheckResVo current : result) {
            current.setTargetMaterial(String.format(template, current.getTargetMaterial(), current.getTargetThickness()));
            current.setSourceMaterial(String.format(template,current.getSourceMaterial(), current.getSourceThickness()));
            if(current.getDiffType() != 0){
                current.setDiffType(1);
            }
        }

        if (StringUtils.hasText(reqVo.getSort()) && StringUtils.hasText(reqVo.getOrder())) {
            if ("sourceTotalCount".equals(reqVo.getSort())) {
                if ("desc".equals(reqVo.getOrder())) {
                    result.sort(Comparator.comparing(ConsistencyCheckResVo::getSourceTotalCount).reversed());
                } else if ("asc".equals(reqVo.getOrder())) {
                    result.sort(Comparator.comparing(ConsistencyCheckResVo::getSourceTotalCount));
                } else {
                    throw SyExceptionUtils.e("未知的排序规则。");
                }
            } else if ("diffMsg".equals(reqVo.getSort())) {
                if ("desc".equals(reqVo.getOrder())) {
                    result.sort(Comparator.comparing(ConsistencyCheckResVo::getDiffMsg).reversed());
                } else if ("asc".equals(reqVo.getOrder())) {
                    result.sort(Comparator.comparing(ConsistencyCheckResVo::getDiffMsg));
                } else {
                    throw SyExceptionUtils.e("未知的排序规则。");
                }
            }
        }

        if(reqVo.getDiffType() != null){
            result.removeIf(e -> !e.getDiffType().equals(reqVo.getDiffType()));
        }

        return new BaseListResVo<>(result);
    }

    public Map<String, String> getReplaceMap() {

        DictType dictType = dictTypeMapper.lambdaQuery().eq(DictType::getDictCode, "plateTextureReplace").one();

        List<DictData> list = dictDataMapper.lambdaQuery().eq(DictData::getDictType, dictType.getId()).list();
        Map<String, String> params = new HashMap<>();
        for (DictData dictData : list) {
            params.put(dictData.getDictValue(), dictData.getDictLabel());
        }
        return params;
    }

    private void wrap(ConsistencyCheckResVo data, int i, ConsistencyCheckDataResVo source) {
        if(source == null){
            return ;
        }
        if(i == 1){
            data.setSourceWorkOrderCode(source.getWorkOrderCode());
            data.setSourceConstructCode(source.getConstructionCode());
            data.setSourceErpCode(source.getErpCode());
            data.setSourceMaterName(source.getMaterName());
            data.setSourcePlmId(source.getPlmId());
            data.setSourceTotalCount(source.getTotalCount());
            data.setSourceMaterial(source.getMaterial());
            data.setSourceThickness(source.getThickness());
            return ;
        }

        data.setTargetWorkOrderCode(source.getWorkOrderCode());
        data.setTargetConstructCode(source.getConstructionCode());
        data.setTargetErpCode(source.getErpCode());
        data.setTargetMaterName(source.getMaterName());
        data.setTargetPlmId(source.getPlmId());
        data.setTargetTotalCount(source.getTotalCount());
        data.setTargetMaterial(source.getMaterial());
        data.setTargetThickness(source.getThickness());

    }



    public void addDiff(int type, String msg, ConsistencyCheckResVo current, List<ConsistencyCheckResVo> result) {
        current.setDiffType(type);
        current.setDiffMsg(msg);
        result.add(current);
    }

    public BaseListResVo<String> conCode(ConsistencyCheckReqVo reqVo) {
        LambdaQueryWrapper<Order> qw = new LambdaQueryWrapper<>();
        if (StringUtils.hasText(reqVo.getConstructionCode())) {
            qw.like(Order::getConstructNo, reqVo.getConstructionCode());
        }
        qw.in(Order::getOrderType, 1,3,4);
        qw.ne(Order::getOrderStatus, 10);
        qw.eq(Order::getDeleted, 0);
        qw.orderByDesc(Order::getId);
        List<Order> orderList = orderMapper.selectList(qw);
        List<String> collect = orderList.stream().map(Order::getConstructNo).distinct().collect(Collectors.toList());
        return new BaseListResVo<>(collect);
    }

    public BaseListResVo<String> diffMsg() {
        List<String> list = new ArrayList<>();
        list.add("找不到该零件");
        list.add("数量不一致");
        list.add("材质不一致");
        list.add("厚度不一致");
        return new BaseListResVo<>(list);
    }

}
